﻿ 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace DeploymentMaxLib
{
    public class Serializer
    {
        /// <summary>
        /// Returns the target namespace for the serializer.
        /// </summary>
        public static string TargetNamespace
        {
            get
            {
                return "http://www.w3.org/2001/XMLSchema";
            }
        }
        /// <summary>
        /// Returns the set of included namespaces for the serializer.
        /// </summary>
        /// <returns>
        /// The set of included namespaces for the serializer.
        /// </returns>
        public static XmlSerializerNamespaces GetNamespaces(bool pSuportNamespaces)
        {
            XmlSerializerNamespaces ns;
            ns = new XmlSerializerNamespaces();
            if (!pSuportNamespaces)
            {
                ns.Add("", "");
            }
            //ns.Add("", "");
            //ns.Add("xs", "http://www.w3.org/2001/XMLSchema");
            //ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
            return ns;
        }


        private static bool DoesSuportNamespaces(System.Type pObjType)
        {
            System.Xml.Serialization.XmlTypeAttribute tAttr = (System.Xml.Serialization.XmlTypeAttribute)Attribute.GetCustomAttribute(pObjType, typeof(System.Xml.Serialization.XmlTypeAttribute));
            return tAttr != null;
        }

        private static bool mPrettyPrint = true;
        /// <summary>
        /// Get or sets the pretty print property.
        /// </summary>
        /// <remarks>
        /// If <b>true</b>, the XML output by the
        /// <see cref="ToXml" /> method is indented in
        /// a hierarchichal manner using one tab character
        /// per level, each level being on a new line. 
        /// If <b>false</b>, no indentation or newline
        /// characters are set in the output.
        /// </remarks>
        public static bool PrettyPrint
        {
            get
            {
                return Serializer.mPrettyPrint;
            }
            set
            {
                Serializer.mPrettyPrint = value;
            }
        }

        /// <summary>
        /// Serializes the <i>Obj</i> to an XML string.
        /// </summary>
        /// <param name="Obj">
        /// The object to serialize.</param>
        /// <param name="ObjType">The object type.</param>
        /// <returns>
        /// The serialized object XML string.
        /// </returns>
        /// <remarks>
        /// The <see cref="PrettyPrint" /> property provides
        /// an easy-to-read formatted XML string.
        /// </remarks>
        public static string ToXml(object pObj)
        {
            var tType = pObj.GetType();
            var tSupNamespases = DoesSuportNamespaces(tType);

            var xsr = new XmlSerializer(tType);

            using (var ms = new MemoryStream())
            {
                using (var xtw = new XmlTextWriter(ms, Encoding.Unicode))
                {

                    if (Serializer.PrettyPrint)
                    {
                        xtw.Formatting = Formatting.Indented;
                        xtw.Indentation = 1;
                        xtw.IndentChar = Convert.ToChar(9);
                    }

                    xtw.Namespaces = true;

                    xsr.Serialize(xtw, pObj, Serializer.GetNamespaces(tSupNamespases));

                    xtw.Close();
                    ms.Close();

                    var tXml = Encoding.Unicode.GetString(ms.GetBuffer());
                    tXml = tXml.Substring(tXml.IndexOf(Convert.ToChar(60)));
                    return tXml.Substring(0, (tXml.LastIndexOf(Convert.ToChar(62)) + 1));

                }
            }

            return "";
        }
        /// <summary>
        /// Creates an object from an XML string.
        /// </summary>
        /// <param name="Xml">
        /// XML string to serialize.</param>
        /// <param name="ObjType">The object type to create.</param>
        /// <returns>
        /// An object of type <i>ObjType</i>.
        /// </returns>

        public static void WriteObjectToXmlFileUnicode(object pObj, string pFileName)
        {
            WriteObjectToXmlFile(pObj, pFileName, Encoding.Unicode);
        }

        public static void WriteObjectToXmlFileASCII(object pObj, string pFileName)
        {
            WriteObjectToXmlFile(pObj, pFileName, Encoding.ASCII);
        }

        public static void WriteObjectToXmlFile(object pObj, string pFileName, Encoding pEncoding)
        {
            using (var xtw = new System.Xml.XmlTextWriter(pFileName, pEncoding))
            {
                var xsr = new System.Xml.Serialization.XmlSerializer(pObj.GetType());
                xsr.Serialize((System.Xml.XmlWriter)xtw, pObj);
                xtw.Close();
            }
        }

        public static T ReadObjectFromXmlFileUnicode<T>(string pFileName, Type pObjType)
        {
            return ReadObjectFromXmlFile<T>(pFileName, pObjType, Encoding.Unicode);
        }

        public static T ReadObjectFromXmlFileASCII<T>(string pFileName, Type pObjType)
        {
            return ReadObjectFromXmlFile<T>(pFileName, pObjType, Encoding.ASCII);
        }

        public static T ReadObjectFromXmlFile<T>(string pFileName, Type pObjType, Encoding pEncoding)
        {
            using (var sr = new System.IO.StreamReader(pFileName, pEncoding))
            {
                using (var xtr = new System.Xml.XmlTextReader(sr))
                {
                    var xsr = new System.Xml.Serialization.XmlSerializer(pObjType);
                    var obj = xsr.Deserialize(xtr);
                    xtr.Close();
                    sr.Close();
                    return (T)obj;
                }
            }
        }

        public static object FromXml(string pXml, System.Type pObjType)
        {
            var xsr = new XmlSerializer(pObjType);

            using (var sr = new StringReader(pXml))
            {
                using (var xtr = new XmlTextReader(sr))
                {
                    if (xsr.CanDeserialize(xtr))
                    {
                        var obj = xsr.Deserialize(xtr);
                        xtr.Close();
                        sr.Close();
                        return obj;
                    }
                }
            }

            return null;
        }

    }
}


